import * as THREE from 'three';
import * as CANNON from "cannon-es";
import Stats from "stats";

import { EffectComposer, RenderPass, ShaderPass, FXAAShader, Detector } from "../../lib";

const userAgent = navigator.userAgent;
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( userAgent );
const isTablet = /iPad|Android/i.test( userAgent );
const isDesktop = !isMobile && !isTablet;

export class Base {

    public stats: Stats;

    public renderer: THREE.WebGLRenderer;
    public camera: THREE.PerspectiveCamera;

    public graphicsWorld: THREE.Scene;
    public physicsWorld: CANNON.World;

    public clock: THREE.Clock;
    composer: EffectComposer;

    constructor () {

        if ( !Detector.webgl ) alert( "浏览器不支持webgl" );

        if ( !isDesktop ) alert( '当前项目仅支持PC端' );

        this.clock = new THREE.Clock();

        this.camera = new THREE.PerspectiveCamera( 80, window.innerWidth / window.innerHeight, 0.01, 1000 );
        this.camera.position.set( 10, 10, 10 );

        this.graphicsWorld = new THREE.Scene();

        // physics
        this.physicsWorld = new CANNON.World();
        this.physicsWorld.gravity.set( 0, -9.81, 0 );
        this.physicsWorld.broadphase = new CANNON.SAPBroadphase( this.physicsWorld );  // 宽相 碰撞检测中的性能优化，性能最好，算法最复杂。
        this.physicsWorld.allowSleep = true;


        // WebGL渲染器
        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setPixelRatio( window.devicePixelRatio );
        this.renderer.setSize( window.innerWidth, window.innerHeight );
        this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
        this.renderer.toneMappingExposure = 1.0;
        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.domElement.id = "canvas";
        this.renderer.domElement.oncontextmenu = e => false;
        document.body.appendChild( this.renderer.domElement );


        this.composer = new EffectComposer( this.renderer );

        const renderPass = new RenderPass( this.graphicsWorld, this.camera );
        const fxaaPass = new ShaderPass( FXAAShader );

        const pixelRatio = this.renderer.getPixelRatio();
        fxaaPass.material[ 'uniforms' ].resolution.value.x = 1 / ( window.innerWidth * pixelRatio );
        fxaaPass.material[ 'uniforms' ].resolution.value.y = 1 / ( window.innerHeight * pixelRatio );

        // Composer
        this.composer = new EffectComposer( this.renderer );
        this.composer.addPass( renderPass );
        this.composer.addPass( fxaaPass );

        window.addEventListener( "resize", () => {
            const { innerWidth, innerHeight } = window;
            this.camera.aspect = innerWidth / innerHeight;
            this.camera.updateProjectionMatrix();
            this.renderer.setSize( innerWidth, innerHeight );
            fxaaPass.uniforms[ 'resolution' ].value.set( 1 / ( innerWidth * pixelRatio ), 1 / ( innerHeight * pixelRatio ) );
            this.composer.setSize( innerWidth * pixelRatio, innerHeight * pixelRatio );

        } );

    }


    initAxesHelper ( size?: number ) {
        const helper = new THREE.AxesHelper( size );
        this.graphicsWorld.add( helper );
    }

    initGridHelper ( size?: number, division?: number, color1?: THREE.ColorRepresentation, color2?: THREE.ColorRepresentation ) {
        const helper = new THREE.GridHelper( size, division, color1, color2 );
        this.graphicsWorld.add( helper );
    }

    initStats () {
        this.stats = new Stats();
        document.body.appendChild( this.stats.dom );
    }

}


